class Game {
  constructor() {
    this.sky = new Sky();
    this.land = new Land(-100);
    this.bird = new Bird();
    this.pipeProducer = new PipePareProducer(-100);
    this.timer = null;
    this.tick = 16; // 移动间隔时间
    this.gameOver = false;
  }

  start() {
    if (this.timer) return;
    if (this.gameOver) window.location.reload();
    this.pipeProducer.startProduct();
    this.timer = setInterval(() => {
      const duration = this.tick / 1000;
      this.sky.move(duration);
      this.land.move(duration);
      this.bird.move(duration);
      this.pipeProducer.pairs.forEach((pair) => {
        pair.move(duration);
      });
      if (this.isGameOver()) {
        this.stop();
        this.gameOver = true;
        console.log("游戏结束");
      }
    }, this.tick);
  }

  stop() {
    clearInterval(this.timer);
    this.timer = null;
    this.bird.stopSwing();
    this.pipeProducer.stopProduce();
  }

  regEvent() {
    window.onkeydown = (e) => {
      if (e.key === "Enter") {
        if (!this.timer) {
          this.start();
        } else {
          this.stop();
        }
      } else if (e.key === " ") {
        this.bird.jump();
      }
    };
  }

  isHit(rect1, rect2) {
    /*
      碰撞算法：
        横向：两个矩形的中心点的横向距离，是否小于矩形宽度之和的一半
        纵向：两个矩形的中心点的纵向距离，是否小于矩形高度之和的一半
    */
    const centerX1 = rect1.left + rect1.width / 2;
    const centerY1 = rect1.top + rect1.height / 2;
    const centerX2 = rect2.left + rect2.width / 2;
    const centerY2 = rect2.top + rect2.height / 2;
    const disX = Math.abs(centerX1 - centerX2);
    const disY = Math.abs(centerY1 - centerY2);

    if (
      disX < (rect1.width + rect2.width) / 2 &&
      disY < (rect1.height + rect2.height) / 2
    ) {
      return true;
    }

    return false;
  }

  isGameOver() {
    if (this.bird.top === this.bird.maxY) {
      return true;
    }

    for (let i = 0; i < this.pipeProducer.pairs.length; i++) {
      const pair = this.pipeProducer.pairs[i];
      if (
        this.isHit(this.bird, pair.upPipe) ||
        this.isHit(this.bird, pair.downPipe)
      ) {
        return true;
      }
    }

    return false;
  }
}

const g = new Game();
g.regEvent();
